#ifndef PRETTY_PRINT_HPP
#define PRETTY_PRINT_HPP

#ifdef _MSC_VER
#pragma once
#endif

#include "jam_ast.hpp"

class scan_context;

struct JAMLIB_EXPORT pretty_print_visitor : public parse_node_visitor
{	
	pretty_print_visitor(std::ostream &output, const scan_context *scanner=NULL);
	virtual ~pretty_print_visitor();

	bool is_null(parse_node_ptr node)
	{
		if (!node) return true;
		return dynamic_node_cast<null_node>(node);
	}

	virtual void visit_append_node(parse_node_base*,parse_node_ptr left_tree,
		parse_node_ptr right_tree);

	virtual void visit_eval_node(parse_node_base*,parse_node_ptr left_tree,
		parse_node_ptr right_tree, condition_type operation);

	virtual void visit_foreach_node(parse_node_base*,parse_node_ptr var_values_tree,
		parse_node_ptr rule_tree, const jam_string& index_var_name, 
		bool is_var_local);

	virtual void visit_if_node(parse_node_base*,parse_node_ptr condition_tree,
		parse_node_ptr then_tree, parse_node_ptr else_tree);

	virtual void visit_include_node(parse_node_base*,parse_node_ptr file_name_tree);

	virtual void visit_list_node(parse_node_base*,const jam_string &expand_string);

	virtual void visit_local_node(parse_node_base*,parse_node_ptr var_list_tree, 
		parse_node_ptr val_list_tree, parse_node_ptr rule_list_tree);

	virtual void visit_module_node(parse_node_base*,parse_node_ptr module_name_tree, 
		parse_node_ptr module_content_tree);

	virtual void visit_class_node(parse_node_base*,parse_node_ptr class_name_tree,
		parse_node_ptr right);

	virtual void visit_null_node(parse_node_base*);

	virtual void visit_on_node(parse_node_base*,parse_node_ptr list_tree,
		parse_node_ptr rule_tree);

	virtual void visit_rule_node(parse_node_base*,parse_node_ptr params_tree, 
		const jam_string &name);

	virtual void visit_rules_node(parse_node_base*,parse_node_ptr rule_tree, 
		parse_node_ptr chained_rules_tree);

	virtual void visit_set_node(parse_node_base*,parse_node_ptr var_names_tree,
		parse_node_ptr val_tree, assignment_operation operation);

	virtual void visit_settings_node(parse_node_base*,parse_node_ptr names_tree,
		parse_node_ptr target_names_tree,parse_node_ptr val_tree, 
		assignment_operation operation);

	virtual void visit_setcomp_node(parse_node_base*,parse_node_ptr rule_content_tree,
		parse_node_ptr param_list_tree, const jam_string &rule_name, 
		bool is_local);

	virtual void visit_setexec_node(parse_node_base*,parse_node_ptr bind_var_tree,
		const jam_string &action_name, const jam_string &os_string, 
		int flags);

	virtual void visit_switch_node(parse_node_base*,parse_node_ptr value_tree,
		parse_node_ptr case_tree);

	virtual void visit_chain_node(parse_node_base*,parse_node_ptr left_tree,
		parse_node_ptr right_tree);

	virtual void visit_case_node(parse_node_base*,parse_node_ptr body_tree,
		const jam_string &value);

	virtual void visit_while_node(parse_node_base*,parse_node_ptr condition_tree,
		parse_node_ptr body_tree);

	virtual void visit_lol_node(parse_node_base*,parse_node_ptr list_elem,
		parse_node_ptr chained_list);

	virtual void visit_return_node(parse_node_base*, parse_node_ptr list_res);

	virtual void visit_left_brace_node(parse_node_base*, parse_node_ptr body_tree,
		parse_node_ptr rbracket_tree);

	virtual void visit_right_brace_node(parse_node_base*);

private:
	void print(parse_node_ptr node,bool do_indent=false);
	void print(const jam_string &str,bool do_indent=false,
		const parse_node_base *node=NULL);
	void do_comments(const parse_node_base &node);

	static const char* oper_to_string(assignment_operation operation);
	static jam_string flags_to_string(int flags);

	std::ostream &output_;	

	const scan_context *scanner_;
	int cur_line_, inside_block_, indent_;
};


#endif //PRETTY_PRINT_HPP
